#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
void do_ls2(char*);
void do_stat(char*);
void show_file_info(char*, struct stat*);
void mode_to_letters(int, char*);
char* uid_to_name(uid_t);
char* gid_to_name(gid_t);
int main(int argc, char* argv[])
{
    if (argc == 1)
    {
        do_ls2(".");
    }
    else if (argc == 2) // 仅有一条路径
    {
        do_ls2(argv[1]);
    }
    else    // 包含多条路径，需要额外写标头
    {
        while (--argc)
        {
            printf("%s:\n", *++argv);
            do_ls2(*argv);
        }
    }

    return 0;
}
void do_ls2(char* path)
{
    DIR* pDir;
    struct dirent* pDirent;
    // 处理打开目录失败
    if ((pDir = opendir(path)) == NULL)
    {
        fprintf(stderr, "ls2: cannot open %s", path);
    }
    else
    {
        // 一条条读取文件名
        while ((pDirent = readdir(pDir)) != NULL)
        {
            do_stat(pDirent->d_name);
        }
        closedir(pDir);
    }
}
void do_stat(char* filename)
{
    // printf("%s\n", filename);
    struct stat info;   // 
    if (stat(filename, &info) == -1)    // 获取信息失败
    {
        perror(filename);
    }
    else
    {
        // 处理获取到的文件属性信息
        show_file_info(filename, &info);
    }
}
void show_file_info(char* filename, struct stat* info)
{
    char modestr[11];
    mode_to_letters(info->st_mode, modestr);
    printf("%s", modestr);
    printf("%4d ", (int)info->st_nlink);
    printf("%-8s ", uid_to_name(info->st_uid));
    printf("%-8s ", gid_to_name(info->st_gid));
    printf("%8ld ", (long)info->st_size);
    printf("%.12s ", 4 + ctime(&info->st_mtime));
    printf("%s\n", filename);
}
void mode_to_letters(int mode, char* str)
{
    strcpy(str, "----------");
    if (S_ISDIR(mode))  // 目录
        str[0] = 'd';
    if (S_ISCHR(mode))  // 字符设备
        str[0] = 'c';
    if (S_ISBLK(mode))  // 块设备
        str[0] = 'b';
    // 处理用户权限
    if (mode & S_IRUSR)
        str[1] = 'r';
    if (mode & S_IWUSR)
        str[2] = 'w';
    if (mode & S_IXUSR)
        str[3] = 'x';
    // 处理用户组权限
    if (mode & S_IRGRP)
        str[4] = 'r';
    if (mode & S_IWGRP)
        str[5] = 'w';
    if (mode & S_IXGRP)
        str[6] = 'x';
    // 处理其他人权限
    if (mode & S_IROTH)
        str[7] = 'r';
    if (mode & S_IWOTH)
        str[8] = 'w';
    if (mode & S_IXOTH)
        str[9] = 'x';
}
char* uid_to_name(uid_t uid)
{
    struct passwd* pPsw;
    static char numStr[10];
    if ((pPsw  = getpwuid(uid)) == NULL)
    {
        sprintf(numStr, "%d", uid);
        return numStr;
    }
    else
    {
        return pPsw->pw_name;
    }
}
char* gid_to_name(gid_t gid)
{
    struct group *pGrp;
    static char numStr[10];
    if ((pGrp  = getgrgid(gid)) == NULL)
    {
        sprintf(numStr, "%d", gid);
        return numStr;
    }
    else
    {
        return pGrp->gr_name;
    }
}






